package com.cn.studey.aspect;

import com.cn.studey.annotations.UserLog;
import com.cn.studey.common.Constant;
import com.cn.studey.common.ResultCode;
import com.cn.studey.entity.vo.ResultVO;
import com.cn.studey.service.UserService;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;

/**
 * @author mjy(此处切面用于记录用户操作)
 * 此处为了学历采用环绕通知
 * @date 2022/01/13
 * @description
 */
@Aspect
@Component
public class UserOperationAop {

    private static final Logger logger = LoggerFactory.getLogger(UserOperationAop.class);

    @Autowired
    private UserService userService;

    @Around(value = "@annotation(com.cn.studey.annotations.UserLog)")
    public Object userOperation(ProceedingJoinPoint pjp) {
        logger.info("<<UserOperationAop 前置通知开始>>");
        RequestAttributes ra = RequestContextHolder.getRequestAttributes();
        ServletRequestAttributes sra = (ServletRequestAttributes) ra;
        HttpServletRequest request = sra.getRequest();
        String token = request.getHeader(Constant.webToken);
        if (token == null) {
            return ResultVO.fail(ResultCode.TOKEN_OVERDUE);
        }
        Long userId = userService.getUserId(token);
        if (userId == null) {
            return ResultVO.fail(ResultCode.TOKEN_CONFLICT);
        }
        Object returnValue = null;
        try {
            //获取方法上面的操作参数
            Object[] args = pjp.getArgs();
            logger.info("原始操作参数 param={}", args[0]);
            //在此执行进入方法前的操作
            returnValue = pjp.proceed();
            //此方法执行完毕，为方法执行之后(获取到操作结果)
        } catch (Throwable throwable) {
            logger.info("用户日志记录异常");
            throwable.printStackTrace();
        } finally {
            if (returnValue instanceof ResultVO) {
                if ((((ResultVO) returnValue).getCode().equals(ResultCode.SUCCESS.getCode()))){
                    logger.info(" 记录操作日志 : returnValue = " + returnValue);
                    //获取注解属性值
                    UserLog userLog = getControllerAnnotation(pjp);
                    //操作数据库保存用户数据(我不做保存数据库操作--不爱)
                    logger.info("获取注解的值为param={}",userLog.toString());
                }
            }
        }
     return returnValue;
    }




    /**
     * 获取注解中对方法的描述信息 （获取注解对象）
     * @param joinPoint 切点
     * @throws Exception
     */
    @SuppressWarnings("rawtypes")
    public static UserLog getControllerAnnotation(JoinPoint joinPoint){
        String targetName ;
        String methodName = null;
        Object[] arguments = null;
        Class targetClass ;
        Method[] methods = null
                ;
        UserLog logAnnotation = null;
        try{
            targetName = joinPoint.getTarget().getClass().getName();
            methodName = joinPoint.getSignature().getName();
            arguments = joinPoint.getArgs();
            targetClass = Class.forName(targetName);
            methods = targetClass.getMethods();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        for (Method method : methods) {
            if (method.getName().equals(methodName)) {
                Class[] clazzs = method.getParameterTypes();
                if (clazzs.length == arguments.length) {
                    logAnnotation = method.getAnnotation(UserLog.class);
                    break;
                }
            }
        }
        return logAnnotation;
    }



}
